/*-------------------------------------------------------------------------
 *
 * numeric.h
 *	  Postgres 的精确数值数据类型的定义。
 *
 * 原始编码 1998, Jan Wieck。2003年大幅修订，Tom Lane。
 *
 * Copyright (c) 1998-2022, PostgreSQL Global Development Group
 *
 * src/include/utils/numeric.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef _PG_NUMERIC_H_
#define _PG_NUMERIC_H_

#include "fmgr.h"

/*
 * NUMERIC typmod中可指定的精度和刻度的限制。精度严格为正，但刻度可以是正数或负数。
 * 负刻度表示小数点前的四舍五入。
 *
 * 注意，下面定义的最小显示刻度为零——我们总是显示小数点前的所有数字，即使刻度为
 * 负数。
 *
 * 注意，数值值的精度和显示刻度的实现限制要大得多——要注意你使用这些的目的！
 */
#define NUMERIC_MAX_PRECISION		1000

#define NUMERIC_MIN_SCALE			(-1000)
#define NUMERIC_MAX_SCALE			1000

/*
 * 用于计算结果的刻度选择的内部限制
 */
#define NUMERIC_MAX_DISPLAY_SCALE	NUMERIC_MAX_PRECISION
#define NUMERIC_MIN_DISPLAY_SCALE	0

#define NUMERIC_MAX_RESULT_SCALE	(NUMERIC_MAX_PRECISION * 2)

/*
 * 对于 inherently inexact 计算，如除法和平方根，我们尝试获得至少这么多有效数字；其
 * 理念是提供的结果不比float8差。
 */
#define NUMERIC_MIN_SIG_DIGITS		16

/* Numeric的实际内容对numeric.c是私有的 */
struct NumericData;
typedef struct NumericData *Numeric;

/*
 * fmgr 接口宏
 */

#define DatumGetNumeric(X)		  ((Numeric) PG_DETOAST_DATUM(X))
#define DatumGetNumericCopy(X)	  ((Numeric) PG_DETOAST_DATUM_COPY(X))
#define NumericGetDatum(X)		  PointerGetDatum(X)
#define PG_GETARG_NUMERIC(n)	  DatumGetNumeric(PG_GETARG_DATUM(n))
#define PG_GETARG_NUMERIC_COPY(n) DatumGetNumericCopy(PG_GETARG_DATUM(n))
#define PG_RETURN_NUMERIC(x)	  return NumericGetDatum(x)

/*
 * numeric.c中的工具函数
 */
extern bool numeric_is_nan(Numeric num);
extern bool numeric_is_inf(Numeric num);
extern int32 numeric_maximum_size(int32 typmod);
extern char *numeric_out_sci(Numeric num, int scale);
extern char *numeric_normalize(Numeric num);

extern Numeric int64_to_numeric(int64 val);
extern Numeric int64_div_fast_to_numeric(int64 val1, int log10val2);

extern Numeric numeric_add_opt_error(Numeric num1, Numeric num2,
									 bool *have_error);
extern Numeric numeric_sub_opt_error(Numeric num1, Numeric num2,
									 bool *have_error);
extern Numeric numeric_mul_opt_error(Numeric num1, Numeric num2,
									 bool *have_error);
extern Numeric numeric_div_opt_error(Numeric num1, Numeric num2,
									 bool *have_error);
extern Numeric numeric_mod_opt_error(Numeric num1, Numeric num2,
									 bool *have_error);
extern int32 numeric_int4_opt_error(Numeric num, bool *error);

#endif							/* _PG_NUMERIC_H_ */
